[摸着原神学图形]AO Volume原理

您所在的位置:网站首页 cubeMap 原理 [摸着原神学图形]AO Volume原理

[摸着原神学图形]AO Volume原理

#[摸着原神学图形]AO Volume原理| 来源: 网络整理| 查看: 265

本文是作者的图形学学习笔记,如有错误疏漏还请各位大佬批评斧正。

参考:[Unity 活动]-游戏专场|从手机走向主机 -《原神》主机版渲染技术分享_哔哩哔哩_bilibili

这里是大佬整理出一份文字版:放牛的星星:《原神》主机版渲染技术要点和解决方案

1. 引入

如下图椅子背后和地上形成了浅浅的AO效果,这是HBAO难以实现的。

AO Volume

原神使用了名为AO Volume的方法,参考自2012年GDC《InFamous 2》讲座。于是笔者找到了相关资料作为本文研究参考。

演示视频截图

上图是演示视频效果,建议观看原视频,看上去就好像汽车周围包裹有一层力场,当力场和道路接触就形成了AO,效果和性能都不错。

演讲介绍链接:https://www.reedbeta.com/talks/ao-fields/PPT链接:Ambient Occlusion Fields and Decals in Infamous 2 - GDC Vault效果视频:https://www.youtube.com/watch?v=06i8cVNFhTw&ab_channel=reedbeta

原神的弋老师是这样概括AO Volume的:“要实现AO volume,首先需要在离线的时候对需要产生AO volume的物体做一个遮挡信息的计算。这个计算是在物体的本地空间(Local space)去做的,生成的遮挡信息保存下来,在运行的时候注入到volume texture中去使用。”也就是某种程度确实可以说物体周围包裹了一层力场

2. 从游戏技术框架层面思考AO

《InFamous 2》讲座首先有一段从整体架构关于游戏AO的思考,笔者个人觉得是游戏设计非常精华的材料,所以在开始研究AO Volume前先概括一下这部分。首先背景《InFamous 2》是一款基于PS3的游戏,支持per-vertex级别的baked AO和SSAO。

baked方法在表现较大尺度场景AO效果不错,但对于更精细的场景需要细分,但这会导致纹理存储负担增加,且只能应对静态资源。SSAO可以适配动态物体,但由于基于屏幕空间,无法访问屏幕以外或被遮挡的几何信息,采样范围相对有限,仅能适配较小尺度的场景。

AO在较大尺度和较小尺度均有适应的方法,而中间尺度则出现空白需要新的技术填补。讲座提出一种思想,并落实为两个实际方法:AO Fields(AO场)和AO Decals(AO贴花),本文选取AO Fields尝试研究。

3. 原理3.1 AO尺度

讲座最关键的线索之一是尺度。对于这一概念,笔者的理解是计算AO强度时,需要检测周围遮挡的范围大小。上面提到SSAO适合小尺度,有多小呢,在研究HBAO时注意到一个采样半球可能只包含几个三角面片、几十个像素。(笔记链接:[摸着原神学图形]HBAO实现与优化,HBAO可以看做SSAO的一种变体)

基于屏幕空间这一特性同样和尺度有关,凹凸信息来自深度图,如果采样球过大,屏幕边缘的像素无法获得屏幕以外的几何信息,则无法绘制与屏幕中部一致的AO。

另一个则是原理上的问题,HBAO在像素点处展开采样半球只能感知到同一表面附近像素的高低,对于与表面存在一定距离的遮挡则是无能为力的(比如原神中的椅子相对于地面)。对于椅子、垃圾桶、车辆等物体附近形成的AO,笔者认为属于中等尺度的范畴,SSAO难以实现。

(碎碎念1:这种尺度物体的AO形状有点像阴影了,能考虑用阴影做吗。碎碎念2:你有考虑过阴影性能消耗吗,如果还是大世界,就算用baked阴影也顶不住吧,更别说美术难度和bake工作量)

3.2 中等尺度的遮挡

还是从物理原理出发,不远处有个物体存在,考虑表面上一点受到的遮挡。

不远处的遮挡物

以该点为球心放置一个单位采样半球(半径不重要,总之遮挡物在半球外),设定空间中的环境光在各个位置和方向都是均匀的,那么这一点受到当前遮挡物体的AO强度为可以设计为(物体到半球上投影面积/半球面积)。AO其实并不要求那么精确的遮挡量计算,所以可以做近似:将投影区域看做为一个标准圆锥。那么在已知采样半球半径的情况下,对于某个不远处的物体只需要遮挡圆锥中心方向 \overrightarrow{occl} 和底面宽度 width 就可以确定这个这个圆锥,从而计算AO。

把视角从表面上的AO计算点切换到遮挡物模型上,在模型空间(local space或model space)中同一个点关于这个模型的遮挡圆锥都是相同的。换个说法,可以把遮挡圆锥当做模型的一部分,模型场景中移动或翻滚时,同一个圆锥的尖头戳到片元关于当前模型的遮挡效果是相同的,比如下图是一种示意图。模型改变了位置和角度,但和它相对静止的位置受到遮挡效果是相同的。

既然存在这样的性质,那能不能把这个模型周围各个位置的遮挡圆锥都保存下来随时取用呢,这就是AO Volume的基础思想,保存的遮挡圆锥如下示意图。

保存遮挡圆锥的Volume Texutre示意图3.3 构造AO VolumeVolume Texture

直接介绍讲座中的方法。比如上面的车辆,先构造一个32×16×8的长方体栅格区域将车辆包裹起来,称为Volume Texture(体积纹理)。对于其中单个立方体(称volume的最小单元为voxel),以voxel中心为相机绘制一个cubemap(类似天空盒)。之后在voxel中对绘制的像素进行近似处理,以所有像素平均方向为遮挡圆锥中心向量\overrightarrow{occl} ,再根据像素数量设置适当的底面宽度 width 。其中每个voxel的rgb通道存储单位中心向量,a存储宽度,则这辆车AO Volume的存储需求为32×16×8×4×8=128Kb=16KB,这一阶段是在模型设计阶段使用工具完成的。

设置Volume范围

如上图,Volume Texture的另一个问题是实际包围尺寸应该多大。讲座的做法是基于模型包围盒,每个面朝外拓展距离 extend=\sqrt{\frac{area}{4\pi \varepsilon}} ,其中area是原始面积、 \varepsilon是标准差取0.25,讲座表示构造方法参考自Malmer的文章,简单来说,前面假定遮挡物在表面的“不远处”,而其实一直到无穷远处依然会有AO,而用有限范围的volume记录意味着更远处的遮挡被扔掉了,这里的标准差值可以衡量被放弃遮挡量。

3.4 计算AO

对于场景中的片元,如果在某个遮挡物的AO Volume范围内则开始计算AO。先将片元的世界坐标逆变换到模型local空间,找到所在voxel提取遮挡向量 \overrightarrow{occl} 和宽度 width,之后基于这些数据以及片元法线计算AO强度。

AO强度

如上图是AO表达式,是一种比较近似的做法, width 越大AO越强,后面的参数 \frac{\overrightarrow{N}\cdot \overrightarrow{occl}}{2\times width}+0.5 介绍如下图。

AO强度2

直观来讲,这一项系数可以在遮挡圆锥角度过大,投影不完全在半球上时削弱AO。比如 \overrightarrow{N}\cdot \overrightarrow{occl}=0 即垂直时只有一半投影在半球上,大概对应0.5的地方,width 越大则越容易到达1。

3.5 整体强度调整

在设计Volume尺寸时提到,根据目前的方法,AO会随着距离越远逐渐减弱(width减小),延伸到无穷远处归零。如果直接套用现有Volume会形成Volume边缘外突然归零的AO,如下图。

原始Volume AO

那么目标效果是什么样的?是车底下AO最强,向外逐渐衰减,在到达Volume边缘归零。于是讲座使用一个线性映射修改了所有voxel的 width 值,将边缘AO设为0,如下图。

调节width强度

具体来说,voxel越靠近边缘width即alpha越小,那么在线性映射中只要让边缘最大的alpha都为0就可以满足所有边缘alpha为0的效果,虽然会削弱整体AO强度,但可以用strength参数补充,最后的效果如下图。

调节后的整体AO3.6 自遮挡修复

靠近模型的片元随着坐标遮挡变化很快,但voxel分辨率有限无法充分记录,从而出现如下图不自然的AO。

自遮挡artifact

理想的方法是检查哪些voxel嵌入到模型之中,但可行性并不高,于是提出了以下方案:设置半个voxel长度的bias让计算AO的片元沿着法线方向远离模型一些,足够修复大部分问题。

自遮挡修复4. 后记

总体来说AO Volume是一种非常Tricky的方法,在许多地方做了相当高程度的近似,但可以看到的是,这些tricks基本是尽量贴合原有的辐射物理规律(贴了,但不多)。这种为了实现游戏内画面,源于生活又不同于生活的技术手段,感觉有一种工程学的美感(?)

笔者在写本篇时完全基于讲座PPT,尝试开发实现什么的,想啊 很想啊,可惜时间、技力、工具和接口熟练度有限,没能同时实现还是挺遗憾的,不过姑且挖个坑吧,万一哪天有空了呢(



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3